package com.jy.api.payUtil;

import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
import lombok.extern.slf4j.Slf4j;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.sax.SAXResult;
import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@SuppressWarnings("deprecation")
@Deprecated
@Slf4j
public abstract class XMLHelper {
	 /***
	  * 將xml文件轉化成java對象
	  * @param clazz 類型
	  * @param xmlPath xml文件路徑
	  * @return
	  */
	 public static Object convertXmlFileToObject(Class<?> clazz, String xmlPath) {
		 Object xmlObject = null;  
	     try {  
            JAXBContext context = JAXBContext.newInstance(clazz);  
            Unmarshaller unmarshaller = context.createUnmarshaller();  
            FileReader fr = null;  
            try {  
                fr = new FileReader(OSUtil.getClassPath()+xmlPath);  
            } catch (FileNotFoundException e) {  
            	log.error("文件找不到", e);
            }  
            xmlObject = unmarshaller.unmarshal(fr);  
	     } catch (JAXBException e) {
			 log.error("文件解析异常", e);
	     }  
	     return xmlObject;
	 }
	 @SuppressWarnings("unchecked")
	public static <T> T convertXmlFileToObjects(Class<?> clazz, String xmlPath){
		 T t = null;
		 try {  
	            JAXBContext context = JAXBContext.newInstance(clazz);  
	            Unmarshaller unmarshaller = context.createUnmarshaller();  
	            FileReader fr = null;  
	            try {  
	                fr = new FileReader(OSUtil.getClassPath()+xmlPath);  
	            } catch (FileNotFoundException e) {
					log.error("文件找不到", e);
	            }  
	            t = (T)unmarshaller.unmarshal(fr);  
		     } catch (JAXBException e) {
			 log.error("文件解析异常", e);
		     }
		 return t;
	 }
	 /***
	  * 將xmlwen文件轉化成java對象
	  * 該方法支持多態，eg:
	  * <code>
	  * pulic class Customer{
	  * 	Person person;
	  * }
	  * public class Person{....}
	  * public class Man extends Person{
	  * ....
	  * }
	  * </code>
	  * @param xmlPath 文件路徑
	  * @param classes 涉及到的java類
	  * @return
	  */
	 public static Object convertXmlFileToObject(String xmlPath,Class<?> ...classes){
		
		 Object xmlObject = null;  
		 FileReader fr = null;  
	     try {  
	         JAXBContext context = JAXBContext.newInstance(classes);  
	         Unmarshaller unmarshaller = context.createUnmarshaller();  
	         try {  
	             fr = new FileReader(OSUtil.getClassPath()+xmlPath);  
	         } catch (FileNotFoundException e) {
				 log.error("文件找不到", e);
	         }  
	         xmlObject = unmarshaller.unmarshal(fr);  
	     } catch (JAXBException e) {
			 log.error("文件解析异常", e);
	     }finally{
	    	 if(fr!=null) {
	    		 try {
					fr.close();
				} catch (IOException e) {
				}
	    	 }
	     }  
	     return xmlObject;
	 }
	 
//	 public static Document map2xml(Map<String, Object> map) throws DocumentException, IOException  {  
//        Iterator<Map.Entry<String, Object>> entries = map.entrySet().iterator();  
//        if(entries.hasNext()){ //获取第一个键创建根节点  
//            Map.Entry<String, Object> entry = entries.next();  
//            Document doc = DocumentHelper.createDocument();  
//            Element root = DocumentHelper.createElement(entry.getKey());  
//            doc.add(root);  
//            map2xml((Map)entry.getValue(), root);  
//            //System.out.println(doc.asXML());  
//            //System.out.println(formatXml(doc));  
//            return doc;  
//        }  
//        return null;  
//    }  
	 public static Document map2xml(Map<String, Object> map,String rootName){
		 Document doc = DocumentHelper.createDocument();  
		 Element root = DocumentHelper.createElement(rootName);
		 doc.add(root);
		 map2xml(map, root); 
		 return doc;
	 }
	 public static void main(String[] args) {
		 Map<String, Object> map = new HashMap<>();
		 map.put("merchid", "dasss");
		 map.put("merchtname", "测试");
		 System.out.println(map2Xml(map, "xml"));
	}
	 public static String map2Xml(Map<String, Object> map,String rootName){
		 Document document = map2xml(map, rootName);
		 return document.asXML();
	 }
	/** 
     * map转xml 
     * @param map 
     * @param body xml元素 
     * @return 
     */  
    private static Element map2xml(Map<String, Object> map, Element body) {  
//    	for(Entry<String, Object> entry:map.entrySet()){
//    		String key = entry.getKey(); 
//    		Object value = entry.getValue();
//    	}
        Iterator<Map.Entry<String, Object>> entries = map.entrySet().iterator();  
        while (entries.hasNext()) {  
            Map.Entry<String, Object> entry = entries.next();  
            String key = entry.getKey();  
            Object value = entry.getValue();  
            if(key.startsWith("@")){    //属性  
                body.addAttribute(key.substring(1, key.length()), value.toString());  
            } else if(key.equals("#text")){ //有属性时的文本  
                body.setText(value.toString());  
            } else {  
                if(value instanceof List ){
                    List list = (List)value;
                    Object obj;
                    for(int i=0; i<list.size(); i++){
                        obj = list.get(i);
                        //list里是map或String，不会存在list里直接是list的，
                        if(obj instanceof Map){
                            Element subElement = body.addElement(key);
                            map2xml((Map)list.get(i), subElement);
                        } else {
                            body.addElement(key).setText((String)list.get(i));
                        }
                    }
                } else if(value instanceof Map ){
                    Element subElement = body.addElement(key);  
                    map2xml((Map)value, subElement);  
                } else {  
                    body.addElement(key).setText(value.toString());  
                }  
            }  
            //System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());  
        }  
        return body;  
    }
    
//    private static Element createElement(Element body,String key,String value){
//    	
//    }
	 /**
	  * 將xml數據轉化成對象
	  * 沒有多態的時，請如下調用
	  * <code>
	  * 	User user = XMLReader.convertXmlStrToObject(xmlDatas,User.class);
	  * </code>
	  * 多態時，調用如下
	  * <code>
	  * 
	  * </code>
	  * @param xmlDatas
	  * @param classes
	  * @return
	  */
	 @SuppressWarnings("unchecked")
	public static <T> T convertXmlStrToObject(String xmlDatas,Class<?> ...classes){
		 T xmlObject = null;  
		 try{
			 JAXBContext context = JAXBContext.newInstance(classes);  
	         Unmarshaller unmarshaller = context.createUnmarshaller();
	         xmlObject = (T)unmarshaller.unmarshal(new StringReader(xmlDatas));
		 }catch (JAXBException e){
			 
		 }
		 return xmlObject;
	 }
	 /**
		 *  将xmlbean转化成xml数据格式
		 * @param cdataElementNames
		 * @param xmlbean
		 * @param classes
		 * @return
		 */
		public static String ojbectToXmlWithCDATA1(List<String>cdataElementNames,Object xmlbean,Class<?>...classes){
			try{
				JAXBContext context = JAXBContext.newInstance(classes); 
				OutputFormat of = new OutputFormat();
				of.setPreserveSpace(true);
		        of.setIndenting(true);
				if(cdataElementNames!=null){
					String[] cdatas = new String[cdataElementNames.size()];
					for(int i=0;i<cdataElementNames.size();i++){
						cdatas[i] = "^"+cdataElementNames.get(i);
					}
					of.setCDataElements(cdatas);
				}
				
				ByteArrayOutputStream op = new ByteArrayOutputStream();  
				XMLSerializer serializer = new XMLSerializer(op, of);
				SAXResult result = new SAXResult(serializer.asContentHandler());  
				Marshaller mar = context.createMarshaller(); 
				mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);  
				mar.marshal(xmlbean, result);  
				return op.toString("utf-8").replaceAll("\r|\n", "");
			}catch(Exception e){
				log.error("异常", e);
				throw new RuntimeException(e);
			} 
		}
		/**
		 * 将xmlbean转化成xml数据格式
		 * @param xmlbean
		 * @param cdataElementNames
		 * @return
		 */
		public static String ojbectToXmlWithCDATA(Object xmlbean,String...cdataElementNames){
			try{
				JAXBContext context = JAXBContext.newInstance(xmlbean.getClass()); 
				OutputFormat of = new OutputFormat();
				of.setPreserveSpace(true);
		        of.setIndenting(true);
				if(cdataElementNames!=null){
					String[] cdatas = new String[cdataElementNames.length];
					for(int i=0;i<cdataElementNames.length;i++){
						cdatas[i] = "^"+cdataElementNames[i];
					}
					of.setCDataElements(cdatas);
				}
				
				ByteArrayOutputStream op = new ByteArrayOutputStream();  
				XMLSerializer serializer = new XMLSerializer(op, of);  
				SAXResult result = new SAXResult(serializer.asContentHandler());  
				Marshaller mar = context.createMarshaller(); 
				mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);  
				mar.marshal(xmlbean, result);  
				return op.toString("utf-8").replaceAll("\r|\n", "");
			}catch(Exception e){
				log.error("异常", e);
				throw new RuntimeException(e);
			} 
		}
		/**
		 * 将xml数据格式转化成json
		 * @param xmlData
		 * @return
		 */
		public static JSONObject xmlToJson(String xmlData){
			try {
				Document document = DocumentHelper.parseText(xmlData);
				Element root = document.getRootElement();
				@SuppressWarnings("unchecked")
				List<Element> elements = root.elements();
				JSONObject params = new JSONObject();
				for(Element e:elements){
					params.put(e.getName(), e.getText());
				}
				return params;
			} catch (DocumentException e) {
				log.error("异常", e);
				throw new RuntimeException(e);
			}
		}
		/**
		 * 将xmlbean转化成 map
		 * @param bean
		 * @return
		 */
		public static Map<String, String> getMap(Object bean){
			try {
				Document document = DocumentHelper.parseText(ojbectToXmlWithCDATA(bean));
				Element root = document.getRootElement();
				@SuppressWarnings("unchecked")
				List<Element> elements = root.elements();
				Map<String, String> params = new HashMap<>();
				for(Element e:elements){
					params.put(e.getName(), e.getText());
				}
				return params;
			} catch (Exception e) {
				log.error("异常", e);
				throw new RuntimeException(e);
			}
		} 
}
